package com.xwj.xuthread.spring.core;

import cn.hutool.core.lang.Assert;
import com.xwj.xuthread.spring.enums.RejectedPolicyTypeEnum;
import lombok.extern.slf4j.Slf4j;

import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

/**
 * @Description TODO
 * @Author xwj
 * @Date 2025/8/24
 */
@Slf4j
public class ThreadPoolManager {
    // 线程池名称 -> 线程池实例映射
    private static final Map<String, XuDynamicThreadPool> threadPools = new ConcurrentHashMap<>();

    public static void registerThreadPool(String threadPoolId, XuDynamicThreadPool threadPool) {
        threadPools.put(threadPoolId, threadPool);
    }

    public XuDynamicThreadPool createThreadPool(ThreadPoolConfig config) {
        String threadPoolName = config.getThreadPoolId();
        if (threadPools.containsKey(threadPoolName)) {
            log.warn("线程池[{}]已存在，返回已有实例", threadPoolName);
            return threadPools.get(threadPoolName);
        }
        XuDynamicThreadPool threadPool = new XuDynamicThreadPool(config.getThreadPoolId(), config.getCorePoolSize(), config.getMaximumPoolSize(), config.getKeepAliveTime(), RejectedPolicyTypeEnum.createPolicy(config.getRejectedHandler()), config.getCapacity());
        threadPools.put(config.getThreadPoolId(), threadPool);
        return threadPool;
    }

    public static void removeThreadPool(String threadPoolId) {
        threadPools.remove(threadPoolId);
    }

    public static XuDynamicThreadPool getThreadPool(String threadPoolId) {
        return threadPools.get(threadPoolId);
    }

    public static Collection<XuDynamicThreadPool> getAllThreadPools() {
        return threadPools.values();
    }

    /**
     * 更新线程池配置
     */
    public static void updateThreadPoolConfig(ThreadPoolConfig config) {
        XuDynamicThreadPool threadPool = getThreadPool(config.getThreadPoolId());

        Integer remoteCorePoolSize = config.getCorePoolSize();
        Integer remoteMaximumPoolSize = config.getMaximumPoolSize();
        Assert.isTrue(remoteCorePoolSize <= remoteMaximumPoolSize, "remoteCorePoolSize must be smaller than remoteMaximumPoolSize.");

        // 如果不清楚为什么有这段逻辑，可以参考 Hippo4j Issue https://github.com/opengoofy/hippo4j/issues/1063
        int originalMaximumPoolSize = threadPool.getMaximumPoolSize();
        if (remoteCorePoolSize > originalMaximumPoolSize) {
            threadPool.setMaximumPoolSize(remoteMaximumPoolSize);
            threadPool.setCorePoolSize(remoteCorePoolSize);
        } else {
            threadPool.setCorePoolSize(remoteCorePoolSize);
            threadPool.setMaximumPoolSize(remoteMaximumPoolSize);
        }

        // 阻塞队列没有常规 set 方法，所以使用反射赋值
        //BlockingQueue workQueue = BlockingQueueTypeEnum.createBlockingQueue(config.getWorkQueue(), config.getQueueCapacity());
        // Java 9+ 的模块系统（JPMS）默认禁止通过反射访问 JDK 内部 API 的私有字段，所以需要配置开放反射权限
        // 在启动命令中增加以下参数，显式开放 java.util.concurrent 包
        // IDE 中通过在 VM options 中添加参数：--add-opens=java.base/java.util.concurrent=ALL-UNNAMED
        // 部署的时候，在启动脚本（如 java -jar 命令）中加入该参数：java -jar --add-opens=java.base/java.util.concurrent=ALL-UNNAMED your-app.jar
        //ReflectUtil.setFieldValue(threadPool, "workQueue", workQueue);

        // 赋值动态线程池其他核心参数
        threadPool.setKeepAliveTime(config.getKeepAliveTime(), TimeUnit.SECONDS);
        threadPool.allowCoreThreadTimeOut(config.getAllowCoreThreadTimeOut());
        threadPool.setRejectedExecutionHandler(RejectedPolicyTypeEnum.createPolicy(config.getRejectedHandler()));

        log.info("更新线程池配置: {}", threadPool);
    }

    /**
     * 关闭线程池
     */
    public static void shutdownThreadPool(String threadPoolName) {
        XuDynamicThreadPool threadPool = threadPools.remove(threadPoolName);
        if (threadPool != null) {
            threadPool.shutdown();
            log.info("关闭线程池[{}]", threadPoolName);
        }
    }
}
